#define __host__
#define __device__
#include <vector_types.h>

#include <algorithm/analytical_model/algorithm/cuda/heliostat/RectangleHeliostat.cuh>
#include <algorithm/analytical_model/algorithm/cuda/inter_op/heliostat/RectangleHeliostat.h>
#include <utils/Utils.h>

using namespace solar::cuda::inter_op;

RectangleHeliostat::RectangleHeliostat()
{
    this->delegate_ptr_ = std::make_shared<solar::cuda::RectangleHeliostat>();
}

void RectangleHeliostat::setNormalAndRotate(const Float3& focus_center,
                                            const Float3& sunray_dir) const
{
    this->delegate_ptr_->setNormalAndRotate(structCopy<float3>(focus_center),
                                            structCopy<float3>(sunray_dir));
}

void RectangleHeliostat::getSubHeliostatVertices(std::vector<Float3>& vertices) const
{
    std::vector<float3> vec;
    this->delegate_ptr_->getSubHeliostatVertices(vec);
    for (const auto& num : vec)
    {
        vertices.emplace_back(structCopy<Float3>(num));
    }
}

void RectangleHeliostat::setPosition(const Float3& pos) const
{
    this->delegate_ptr_->pos_ = structCopy<float3>(pos);
}

void RectangleHeliostat::setSize(const Float3& size) const
{
    this->delegate_ptr_->size_ = structCopy<float3>(size);
}

auto RectangleHeliostat::getVertices() const -> std::vector<Float3>
{
    std::vector<Float3> ret;
    for (auto current_vertex : this->delegate_ptr_->vertices_)
    {
        ret.emplace_back(structCopy<Float3>(current_vertex));
    }
    return ret;
}

auto RectangleHeliostat::getImagePlaneAxis() const -> std::tuple<Float3, Float3, Float3>
{
    auto result = this->delegate_ptr_->getImagePlaneAxis();
    auto& x_axis = std::get<0>(result);
    auto& y_axis = std::get<1>(result);
    auto& z_axis = std::get<2>(result);
    return {structCopy<Float3>(x_axis), structCopy<Float3>(y_axis), structCopy<Float3>(z_axis)};
}

auto RectangleHeliostat::getFocusCenter() const -> Float3
{
    return structCopy<Float3>(this->delegate_ptr_->focus_center_);
}

auto RectangleHeliostat::getPosition() const -> Float3
{
    return structCopy<Float3>(this->delegate_ptr_->pos_);
}

auto RectangleHeliostat::getSize() const -> Float3
{
    return structCopy<Float3>(this->delegate_ptr_->size_);
}

auto RectangleHeliostat::getNormal() const -> Float3
{
    return structCopy<Float3>(this->delegate_ptr_->normal_);
}

auto RectangleHeliostat::getGap() const -> Float2
{
    return structCopy<Float2>(this->delegate_ptr_->gap_);
}

void RectangleHeliostat::setGap(const Float2& gap) const
{
    this->delegate_ptr_->gap_ = structCopy<float2>(gap);
}

auto RectangleHeliostat::getRowAndColumn() const -> Int2
{
    return structCopy<Int2>(this->delegate_ptr_->row_col_);
}

void RectangleHeliostat::setRowAndColumn(const Int2 row_col) const
{
    this->delegate_ptr_->row_col_ = structCopy<int2>(row_col);
}

auto RectangleHeliostat::getBelongingGridId() const -> int
{
    return this->delegate_ptr_->belonging_grid_id_;
}

void RectangleHeliostat::setBelongingGridId(int grid_id) const
{
    this->delegate_ptr_->belonging_grid_id_ = grid_id;
}

auto RectangleHeliostat::getPtr() const -> solar::cuda::RectangleHeliostat*
{
    return this->delegate_ptr_.get();
}
